package com.orange.core.service.shop.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Opt;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.orange.core.pojo.enums.ShopStatus;
import com.orange.core.service.shop.ShopService;
import com.orange.core.mapper.floor.FloorMapper;
import com.orange.core.mapper.mallArea.MallAreaMapper;
import com.orange.core.mapper.shop.ShopMapper;
import com.orange.core.mapper.shopCategory.ShopCategoryMapper;
import com.orange.core.pojo.PageReqDto;
import com.orange.core.pojo.entity.floor.Floor;
import com.orange.core.pojo.entity.mallArea.MallArea;
import com.orange.core.pojo.entity.shop.Shop;
import com.orange.core.pojo.entity.shop.dto.ShopDTO;
import com.orange.core.pojo.entity.shop.vo.ShopVO;
import com.orange.core.pojo.entity.shopCategory.ShopCategory;
import com.orange.core.pojo.req.shop.ShopPageReq;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author lwm
 * @description 针对表【shop(店铺表)】的数据库操作Service实现
 * @createDate 2025-05-24 20:33:59
 */
@Service
@RequiredArgsConstructor
public class ShopServiceImpl extends ServiceImpl<ShopMapper, Shop>
        implements ShopService {

    private final ShopCategoryMapper shopCategoryMapper;

    private final FloorMapper floorMapper;

    private final ShopMapper shopMapper;

    private final MallAreaMapper mallAreaMapper;

    @Override
    public Page<ShopVO> page(PageReqDto<ShopPageReq> pageReqDto) {
        // 处理空请求参数
        if (pageReqDto == null) {
            pageReqDto = new PageReqDto();
            pageReqDto.setCondition(new ShopPageReq());
        } else if (pageReqDto.getCondition() == null) {
            pageReqDto.setCondition(new ShopPageReq());
        }

        ShopPageReq condition = pageReqDto.getCondition();
        Page<Shop> page = new Page<>(pageReqDto.getPage(), pageReqDto.getSize());
        //构建查询条件
        LambdaQueryWrapper<Shop> shopQuery = buildShopQueryWrapper(condition);

        page = shopMapper.selectPage(page, shopQuery);
        return convertToShopVOPage(page);
    }

    @Override
    public ShopVO info(int id) {
        Shop shop = shopMapper.selectById(id);
        Assert.notNull(shop, "店铺不存在");
        //获取楼层信息
        Floor floor = floorMapper.selectById(shop.getFloorId());
        ShopVO shopVO = new ShopVO();
        BeanUtil.copyProperties(shop, shopVO);
//        Optional.ofNullable(shop.getPointsRatio()).ifPresent(pointsRatio -> shopVO.setPointsRatio(pointsRatio * 100));
        if (floor != null) {
            shopVO.setFloorName(floor.getFloorName());
            //获取区域信息
            MallArea mallArea = mallAreaMapper.selectById(floor.getAreaId());
            if (mallArea != null) {
                shopVO.setAreaId(mallArea.getId());
                shopVO.setAreaName(mallArea.getAreaName());
            }
        }
        //获取店铺分类
        ShopCategory shopCategory = shopCategoryMapper.selectById(shop.getCategoryId());
        if (shopCategory != null) {
            shopVO.setCategoryName(shopCategory.getCategoryName());
        }
        return shopVO;
    }

    @Override
    @Transactional
    public boolean save(ShopDTO shopDTO) {
        Shop shop = new Shop();
        BeanUtil.copyProperties(shopDTO, shop);
//        Optional.ofNullable(shopDTO.getPointsRatio()).ifPresent(pointsRatio -> shop.setPointsRatio(pointsRatio / 100));
        boolean result = this.save(shop);
        return result;
    }

    @Override
    @Transactional
    public boolean update(ShopDTO shopDTO) {
        Shop shop = new Shop();
        BeanUtil.copyProperties(shopDTO, shop);
//        Optional.ofNullable(shopDTO.getPointsRatio()).ifPresent(pointsRatio -> shop.setPointsRatio(pointsRatio / 100));
        boolean result = this.updateById(shop);
        return result;
    }

    @Override
    @Transactional
    public boolean deleteShopByIds(Integer[] ids) {
        List<Integer> list = Arrays.asList(ids);
        boolean result = this.updateBatchById(list.stream().map(id -> {
            Shop shop = new Shop();
            shop.setId(id);
            shop.setStatus(ShopStatus.CLOSED.getCode());
            return shop;
        }).collect(Collectors.toList()));
        return result;
    }

    private Page<ShopVO> convertToShopVOPage(Page<Shop> page) {
        if (CollectionUtils.isEmpty(page.getRecords())) {
            return new Page<>(page.getPages(), page.getSize(), page.getTotal());
        }

        // 获取关联数据
        //获取分类ids
        Set<Integer> categoryIds = page.getRecords().stream()
                .map(Shop::getCategoryId)
                .collect(Collectors.toSet());
        //获取分类map
        Map<Integer, ShopCategory> shopCategoryMap = getShopCategoryMap(categoryIds);

        //获取楼层ids
        List<Integer> floorIds = page.getRecords().stream()
                .map(Shop::getFloorId)
                .distinct()
                .collect(Collectors.toList());
        //获取楼层map
        Map<Integer, Floor> floorMap = getFloorMap(floorIds);

        Map<Integer, MallArea> mallAreaMap = getMallAreaMap(floorMap.values());

        // 转换VO
        List<ShopVO> shopVOS = page.getRecords().stream()
                .map(shop -> convertToShopVO(shop, shopCategoryMap, floorMap, mallAreaMap))
                .collect(Collectors.toList());

        Page<ShopVO> shopVOPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        shopVOPage.setRecords(shopVOS);
        return shopVOPage;
    }

    /**
     * 构建查询条件
     *
     * @param condition
     * @return
     */
    private LambdaQueryWrapper<Shop> buildShopQueryWrapper(ShopPageReq condition) {
        LambdaQueryWrapper<Shop> shopQuery = new LambdaQueryWrapper<>();

        if (condition.getStatus() != null) {
            shopQuery.eq(Shop::getStatus, condition.getStatus());
        }

        if (condition.getShopId() != null) {
            shopQuery.like(Shop::getId, condition.getShopId());
        }

        if (condition.getCategoryId() != null) {
            shopQuery.eq(Shop::getCategoryId, condition.getCategoryId());
        }

        if (condition.getName() != null) {
            shopQuery.like(Shop::getName, condition.getName());
        }

        if (condition.getAreaId() != null || condition.getFloorId() != null) {
            LambdaQueryWrapper<Floor> floorQuery = new LambdaQueryWrapper<>();
            if (condition.getAreaId() != null) {
                floorQuery.eq(Floor::getAreaId, condition.getAreaId());
            }
            if (condition.getFloorId() != null) {
                floorQuery.eq(Floor::getId, condition.getFloorId());
            }

            List<Floor> filteredFloors = floorMapper.selectList(floorQuery);
            if (!filteredFloors.isEmpty()) {
                List<Integer> floorIds = filteredFloors.stream()
                        .map(Floor::getId)
                        .collect(Collectors.toList());
                shopQuery.in(Shop::getFloorId, floorIds);
            } else {
                shopQuery.apply("1=0");
            }
        }
        return shopQuery;
    }

    private Map<Integer, ShopCategory> getShopCategoryMap(Set<Integer> categoryIds) {
        if (CollectionUtils.isEmpty(categoryIds)) {
            return Collections.emptyMap();
        }
        return shopCategoryMapper.selectBatchIds(categoryIds).stream()
                .collect(Collectors.toMap(ShopCategory::getId, Function.identity()));
    }

    private Map<Integer, Floor> getFloorMap(List<Integer> floorIds) {
        if (CollectionUtils.isEmpty(floorIds)) {
            return Collections.emptyMap();
        }
        return floorMapper.selectBatchIds(floorIds).stream()
                .collect(Collectors.toMap(Floor::getId, Function.identity()));
    }

    private Map<Integer, MallArea> getMallAreaMap(Collection<Floor> floors) {
        if (CollectionUtils.isEmpty(floors)) {
            return Collections.emptyMap();
        }
        List<Integer> areaIds = floors.stream()
                .map(Floor::getAreaId)
                .distinct()
                .collect(Collectors.toList());
        return mallAreaMapper.selectBatchIds(areaIds).stream()
                .collect(Collectors.toMap(MallArea::getId, Function.identity()));
    }

    private ShopVO convertToShopVO(Shop shop,
                                   Map<Integer, ShopCategory> shopCategoryMap,
                                   Map<Integer, Floor> floorMap,
                                   Map<Integer, MallArea> mallAreaMap) {
        ShopVO shopVO = new ShopVO();
        BeanUtils.copyProperties(shop, shopVO);
//        Optional.ofNullable(shop.getPointsRatio()).ifPresent(pointsRatio -> shopVO.setPointsRatio(pointsRatio * 100));
        // 设置分类名称
        ShopCategory category = shopCategoryMap.get(shop.getCategoryId());
        shopVO.setCategoryName(category != null ? category.getCategoryName() : null);

        // 设置楼层和区域信息
        Floor floor = floorMap.get(shop.getFloorId());
        if (floor != null) {
            shopVO.setFloorName(floor.getFloorName());
            shopVO.setAreaId(floor.getAreaId());

            MallArea area = mallAreaMap.get(floor.getAreaId());
            shopVO.setAreaName(area != null ? area.getAreaName() : null);
        }
        return shopVO;
    }
}




